﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace ConsoleAppFramework.Util
{
    public class HttpHelper
    {
        #region HttpClient
        private static HttpClient _httpClient;
        public static HttpClient httpClient
        {
            get
            {
                if (_httpClient == null)
                {
                    _httpClient = new HttpClient(new HttpClientHandler() { UseCookies = false });
                    _httpClient.Timeout = new TimeSpan(0, 1, 0);

                }
                return _httpClient;
            }
            set { _httpClient = value; }
        }

        #endregion

        #region Get请求
        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="url">目标链接</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string url, Dictionary<string, string> header = null)
        {
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpResponseMessage response = await httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode();//用来抛异常的
            return await response.Content.ReadAsStringAsync();
        }

        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="url">目标链接</param>
        /// <returns></returns>
        public static async Task<ResponseWithStatus> GetAsyncWithStatus(string url, Dictionary<string, string> header = null)
        {
            ResponseWithStatus responseWithStatus = new ResponseWithStatus();
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpResponseMessage response = await httpClient.GetAsync(url);
            responseWithStatus.Status = (int)response.StatusCode;
            responseWithStatus.ResponseString = await response.Content.ReadAsStringAsync();
            return responseWithStatus;
        }

        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="url">目标链接</param>
        /// <returns></returns>
        public static async Task<ResponseWithStatus> GetAsyncWithStatus(string url, int TimeOutSeconds, Dictionary<string, string> header = null)
        {
            ResponseWithStatus responseWithStatus = new ResponseWithStatus();
            if (TimeOutSeconds > 0)
            {
                httpClient.Timeout = TimeSpan.FromSeconds(TimeOutSeconds);
            }
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpResponseMessage response = await httpClient.GetAsync(url);
            responseWithStatus.Status = (int)response.StatusCode;
            responseWithStatus.ResponseString = await response.Content.ReadAsStringAsync();
            return responseWithStatus;
        }

        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="url">目标地址</param>
        /// <param name="queryParam">查询参数</param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<string> GetAsyncQuery(string url, Dictionary<string, string> queryParam, Dictionary<string, string> header = null)
        {
            url = BuildGetUrl(url, queryParam);//有查询参数
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpResponseMessage response = await httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode();//用来抛异常的
            return await response.Content.ReadAsStringAsync();
        }

        public static string Get(string url, Dictionary<string, string> queryParam)
        {
            url = BuildGetUrl(url, queryParam);//有查询参数
            HttpResponseMessage response = httpClient.GetAsync(url).Result;
            response.EnsureSuccessStatusCode();//用来抛异常的
            return response.Content.ReadAsStringAsync().Result;
        }
        public static string Get(string url)
        {
            string result;
            try
            {
                using (var client = new HttpClient())
                {
                    var response = client.GetAsync(url).Result;
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                        throw new Exception("请求状态不成功，状态码：" + response.StatusCode);
                    }
                    result = response.Content.ReadAsStringAsync().Result;
                }
            }
            catch (Exception e)
            {
                throw new Exception("请求异常" + e.Message);
            }
            return result;
        }
        public static string HttpGet(string Url, string query, Encoding encoding = null)
        {
            var request = (HttpWebRequest)WebRequest.Create(Url + (query == "" ? "" : "?") + query);
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";

            var response = (HttpWebResponse)request.GetResponse();
            var myResponseStream = response.GetResponseStream();
            if (encoding == null) encoding = Encoding.UTF8;
            var myStreamReader = new StreamReader(myResponseStream, encoding);
            var retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }
        #endregion

        #region Post请求
        /// <summary>
        /// Post异步请求
        /// </summary>
        /// <para>FormUrlEncoded</para>
        /// <param name="url">请求地址</param>
        /// <param name="body">请求</param>
        /// <param name="header">请求头</param>
        /// <returns></returns>
        public static async Task<string> PostAsync(string url, Dictionary<string, string> body, Dictionary<string, string> header = null)
        {
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpContent content = new FormUrlEncodedContent(body);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            HttpResponseMessage response = await httpClient.PostAsync(url, content);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
        /// <summary>
        /// Post异步请求
        /// </summary>
        /// <param name="url">目标链接</param>
        /// <param name="postData">提交到Web的Json格式的数据：如:{"ErrCode":"FileErr"}</param>
        /// <returns>返回的字符串</returns>
        public static async Task<string> PostAsync(string url, string postData, IEnumerable<KeyValuePair<string, string>> header = null)
        {
            HttpContent content = new StringContent(postData);
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            content.Headers.ContentType.CharSet = "utf-8";
            HttpClientHandler httpHandler = new HttpClientHandler() { UseCookies = false };

            using (HttpClient httpClient = new HttpClient(httpHandler))
            {
                if (header != null)
                {
                    httpClient.DefaultRequestHeaders.Clear();
                    foreach (KeyValuePair<string, string> item in header)
                    {
                        httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                    }
                }
                HttpResponseMessage response = await httpClient.PostAsync(url, content);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();

            }
        }

        /// <summary>
        /// POST发送请求
        /// </summary>
        /// <param name="url">Url地址</param>
        /// <param name="contentType">编码类型</param>
        /// <param name="requestData">数据</param>
        /// <param name="headerParams"></param>
        public static string SendPostHttpRequest(string url, string contentType, string requestData, Dictionary<string, string> headerParams)
        {
            try
            {
                WebRequest request = WebRequest.Create(url);
                request.Method = "POST";
                byte[] postBytes = null;
                if (headerParams != null)
                {
                    foreach (KeyValuePair<string, string> pair in headerParams)
                    {
                        request.Headers.Add(pair.Key, pair.Value);
                    }
                }
                request.ContentType = contentType;
                postBytes = Encoding.UTF8.GetBytes(requestData);
                request.ContentLength = postBytes.Length;
                using (Stream outStream = request.GetRequestStream())
                {
                    outStream.Write(postBytes, 0, postBytes.Length);
                }
                string result;
                using (WebResponse response = request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                        {
                            result = reader.ReadToEnd();
                        }
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        #endregion

        /// <summary>
        /// Put异步请求
        /// </summary>
        /// <param name="url">请求路径</param>
        /// <param name="body">请求主体</param>
        /// <param name="header">请求头</param>
        /// <returns></returns>
        public static async Task<string> PutAsync(string url, Dictionary<string, string> body, Dictionary<string, string> header = null)
        {
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }
            HttpContent content = new FormUrlEncodedContent(body);
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
            HttpResponseMessage response = await httpClient.PutAsync(url, content);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }

        /// <summary>
        /// Delete异步请求
        /// </summary>
        /// <param name="url">请求路径</param>
        /// <param name="header">请求头</param>
        /// <returns></returns>
        public static async Task<string> DeleteAsync(string url, Dictionary<string, string> header = null)
        {
            if (header != null)
            {
                httpClient.DefaultRequestHeaders.Clear();
                foreach (KeyValuePair<string, string> item in header)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
            }

            HttpResponseMessage response = await httpClient.DeleteAsync(url);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }

        #region 其他辅助方法
        public static string BuildGetUrl(string url, Dictionary<string, string> paramDic)
        {
            if (paramDic == null || paramDic.Count == 0)
            {
                return url;
            }
            return url + "?" + UrlParamsString(paramDic);
        }

        /// <summary>
        /// Url参数字符串
        /// </summary>
        /// <param name="dic">参数字典</param>
        /// <returns></returns>
        public static string UrlParamsString(IDictionary<string, string> dic)
        {
            var str = new StringBuilder();
            foreach (var temp in dic)
            {
                str.Append(HttpUtility.UrlEncode(temp.Key) + "=" + HttpUtility.UrlEncode(temp.Value) + "&");
            }

            str.Remove(str.Length - 1, 1);
            return str.ToString();
        }
        #endregion
    }

    public class ResponseWithStatus
    {
        /// <summary>
        /// 返回的http正文文本
        /// </summary>
        public string ResponseString { get; set; }
        /// <summary>
        /// http状态码
        /// </summary>
        public int Status { get; set; }
    }
}
